package com.airS.task.fileMgr.controller.file;

import com.airS.task.fileMgr.common.anno.Invoke;
import com.airS.task.fileMgr.common.constants.FilemgrConstants;
import com.airS.task.fileMgr.common.em.LogType;
import com.airS.task.fileMgr.common.page.Page;
import com.airS.task.fileMgr.common.response.BaseResponse;
import com.airS.task.fileMgr.common.response.ResponseCode;
import com.airS.task.fileMgr.controller.base.SupportController;
import com.airS.task.fileMgr.example.mgr.YunfileExample;
import com.airS.task.fileMgr.model.mgr.FileInfo;
import com.airS.task.fileMgr.model.mgr.FileOperalog;
import com.airS.task.fileMgr.model.mgr.Yunfile;
import com.airS.task.fileMgr.model.mgr.YunfileTree;
import com.airS.task.fileMgr.query.mgr.FileOperalogQuery;
import com.airS.task.fileMgr.query.mgr.YunfileQuery;
import com.airS.task.fileMgr.security.shiro.realm.SystemAuthorizingRealm;
import com.airS.task.fileMgr.service.mgr.FdfsService;
import com.airS.task.fileMgr.service.mgr.FileOperalogService;
import com.airS.task.fileMgr.service.mgr.YunfileService;
import com.airS.task.fileMgr.utils.collection.CollectionUtils;
import com.airS.task.fileMgr.utils.file.FileUtils;
import com.airS.task.fileMgr.utils.shiro.SecurityUtils;
import com.airS.task.fileMgr.utils.url.UrlUtils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 文件管理
 * Created by alan on 2017/3/9.
 */
@Controller
@RequestMapping("/file")
public class FileController extends SupportController implements InitializingBean{

    private static Logger logger = LoggerFactory.getLogger(FileController.class);

    private static final String DEFAULT_ACTIVE_KEY_LINK = "activeKeyLink";

    @Value("${upload.folder.release}")
    private String uploadFolderRelease = "/apps/resumableUpload/release/";

    @Value("${upload.folder.temp}")
    private String uploadFolderTemp = "/apps/resumableUpload/temp/";

    @Autowired
    private FileOperalogService fileOperalogService;

    @Autowired
    private YunfileService yunfileService;

    @Value("${file.download.prefix}")
    private String fileDownloadPrefix;

//    @Value("${openOffice.home}")
//    private String openOfficeHome;
//
//    @Value("${openOffice.host}")
//    private String openOfficeHost;
//
//    @Value("${openOffice.port}")
//    private int openOfficePort;

    @Value("${swftools.pdf.exePath}")
    private String pdfExePath;

    @Value("${swftools.png.exePath}")
    private String pngExePath;

    @Value("${swftools.jpeg.exePath}")
    private String jpegExePath;

    @Value("${libreOffice.home}")
    private String libreOfficeHome;

    @Value("${libreOffice.port}")
    private int libreOfficePort;

    @Autowired
    private FdfsService fdfsService;

    private String swfSplit = "#%&#";

    /**
     * 批量文件断点续传
     * @param file
     * @param fileSign
     * @param startSize
     * @param totalSize
     * @param fileName
     * @param remark
     * @param uploadFolderId
     * @param jsessionId
     * @return
     * @throws IOException
     * @descipt  临时文件名格式：fileSign
     *           临时目录：E:\apps\resumableUpload\jsessionId\
     *           正式文件名格式：fileName，以最终名字命名
     */
    @RequestMapping("/fileUpload")
    @ResponseBody
    @Invoke(logType = LogType.FILE_LOG)
    public Object fileUpload(@RequestParam(name = "shardData", required = true)MultipartFile file,
                             @RequestParam(name = "fileSign", required = true)String fileSign,
                             @RequestParam(name = "startSize", required = true)Double startSize,
                             @RequestParam(name = "totalSize", required = true)Double totalSize,
                             @RequestParam(name = "fileName", required = true)String fileName,
                             @RequestParam(name = "remark", required = false)String remark,
                             @RequestParam(name = "uploadFolderId", required = true)Integer uploadFolderId,
                             @RequestParam(name = "jsessionId", required = true)String jsessionId) throws IOException {
        BaseResponse baseResponse = new BaseResponse();
        File newFile = null;
        File swfFile = null;
        File destFile = null;
        if(fileName.length() > 150){
            fileName = fileName.substring(0, 73) + "..." + fileName.substring(fileName.length() - 74, fileName.length());
        }
        if(remark.length() > 150){
            remark = remark.substring(0, 73) + "..." + remark.substring(remark.length() - 74, remark.length());
        }
        try{
            SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
            if(principal != null && StringUtils.isNotBlank(principal.getGroupName())){
                if(file.getBytes().length == 0){
                    baseResponse.setCode(ResponseCode.PARAM_FAIL);
                    baseResponse.setData(-2);
                    baseResponse.setMsg("不能上传空文件");
                    return baseResponse;
                }
                if(startSize > totalSize){
                    // 已上传完毕
                    baseResponse.setCode(ResponseCode.PARAM_FAIL);
                    baseResponse.setData(-1);
                    return baseResponse;
                }
                // step 1 判断文件是否在临时目录列表
                String tempFolderStr = uploadFolderTemp + jsessionId;   // 个人临时文件夹路径
                File tempFolder = new File(tempFolderStr);  // 临时文件夹
                File tempFile = new File(tempFolderStr + "/" + fileSign + ".tmp");  // 临时文件
                // 临时文件夹是否存在，不存在则新建一个
                if(!tempFolder.exists()){
                    tempFolder.mkdir();
                }
                if(!tempFile.exists()){
                    // 不存在且分片大小大于0，重定向分片
                    if(startSize > 0){
                        baseResponse.setCode(ResponseCode.PARAM_FAIL);
                        baseResponse.setData(0);
                        return baseResponse;
                    }
                    // 不存在则新建
                    if(!tempFile.createNewFile()){
                        // 创建临时文件异常处理
                        tempFile.delete();
                        baseResponse.setCode(ResponseCode.PARAM_FAIL);
                        baseResponse.setData(0);
                        return baseResponse;
                    }
                }
                // step 2 比对当前startSize是否与当前存在文件的length相同，如果不同则返回当前文件的offset给前端
                Long offset = tempFile.length();
                if(offset.compareTo(totalSize.longValue()) == 0){
                    // 如果当前文件已经写完，则无需处理
                }else if(offset.compareTo(startSize.longValue()) != 0){
                    baseResponse.setCode(ResponseCode.PARAM_FAIL);
                    baseResponse.setData(offset);
                    return baseResponse;
                }else{
                    // step 3 如果相同则追加写入
                    FileOutputStream fileWirte = new FileOutputStream(tempFile, true);
                    fileWirte.write(file.getBytes());
                    fileWirte.flush();
                    fileWirte.close();
                }
                baseResponse.setData(tempFile.length());
                // step 4 转移文件到正式目录
                offset = tempFile.length();
                if(offset.compareTo(totalSize.longValue()) == 0){
                    // 检查是否是文件夹
                    Yunfile yunfile = uploadFolderId == 0 ? null : yunfileService.queryYunfileById(uploadFolderId);
                    if(uploadFolderId == 0 || (yunfile != null && principal.getGroupName().equals(yunfile.getGroupName()) && FilemgrConstants.FILE_TYPE.T02.equals(yunfile.getFileType()))){
                        // 临时文件夹是否存在，不存在则新建一个
                        String releaseFolder = uploadFolderRelease + jsessionId;
                        File releaseFile = new File(releaseFolder); // 正式目录
                        if(!releaseFile.exists()){
                            releaseFile.mkdir();
                        }
                        // TODO 文件后缀匹配使用正则
                        String uploadFilePath = null;
                        // TODO 临时处理 tar.gz
                        String ext = fileName.indexOf(".") == -1 ? "unknown" : fileName.endsWith("tar.gz") ? "tar.gz" : fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
                        String randomId = UUID.randomUUID().toString();
                        String randomFileName = randomId + "." + ext;
                        newFile = new File(releaseFolder + "/" + randomFileName);
                        if(FileUtils.copySingleFile(tempFile, newFile)){
                            try{
                                FileInfo fileInfo = new FileInfo(fileName, StringUtils.isBlank(ext) ? "tar.gz" : ext, FileUtils.fileToByteArray(newFile));
                                // step 5 转移文件到fastdfs
                                uploadFilePath = fdfsService.uploadToFastDFS(fileInfo);
                                try {
                                    if(newFile.length() < 10485760){
                                        // 生成swf
                                        if (".docx.doc.xls.xlsx.pptx.ppt.odt.sxw.rtf.wps.txt.".contains("." + ext + ".")) {
                                            destFile = new File(releaseFolder + "/" + randomId + ".pdf");
                                            FileUtils.libreOffice2PDF(libreOfficeHome,libreOfficePort, newFile, destFile);
                                            FileUtils.pdf2swf(destFile.getPath(), pdfExePath);
                                            swfFile = new File(releaseFolder + "/" + randomId + ".swf");
                                        } else if ("pdf".equals(ext)) {
                                            FileUtils.pdf2swf(newFile.getPath(), pdfExePath);
                                            swfFile = new File(releaseFolder + "/" + randomId + ".swf");
                                        } else if (".jpg.jpeg.".contains("." + ext + ".")) {
                                            FileUtils.pdf2swf(newFile.getPath(), jpegExePath);
                                            swfFile = new File(releaseFolder + "/" + randomId + ".swf");
                                        } else if ("png".equals(ext)) {
                                            FileUtils.pdf2swf(newFile.getPath(), pngExePath);
                                            swfFile = new File(releaseFolder + "/" + randomId + ".swf");
                                        }
                                        if (swfFile != null) {
                                            FileInfo swfFileInfo = new FileInfo(swfFile.getName(), "swf", FileUtils.fileToByteArray(swfFile));
                                            uploadFilePath += swfSplit + fdfsService.uploadToFastDFS(swfFileInfo);
                                        }
                                    }
                                } catch (Exception e){
                                    e.printStackTrace();
                                    logger.error("文件转换异常,请检查: filePath: {}", swfFile);
                                }
                            }catch(Exception e){
                                e.printStackTrace();
                                logger.error("文件上传至fastdfs异常,请检查: filePath: {}", newFile);
                                if(newFile != null && newFile.exists())
                                    newFile.delete();
                                if(swfFile != null && swfFile.exists())
                                    swfFile.delete();
                                if(destFile != null && destFile.exists())
                                    destFile.delete();
                                baseResponse.setCode(ResponseCode.PARAM_FAIL);
                                baseResponse.setData(-2);
                                baseResponse.setMsg("文件转移至fdfs异常，请重试");
                                return baseResponse;
                            }
                        }

                        // 上传fdfs成功，则删除release文件
                        newFile.delete();

                        // TODO 以下操作暂不做事务控制

                        // 新增文件入库
                        Yunfile yunfileBuild = new Yunfile();
                        yunfileBuild.setParentId(uploadFolderId == 0 ? 0 : yunfile.getFileId());
                        yunfileBuild.setParentIds(uploadFolderId == 0 ? "0" : yunfile.getParentIds() + "," + yunfile.getFileId());
                        yunfileBuild.setRemark(remark);
                        yunfileBuild.setCreatePeople(principal.getEmployeeName());
                        yunfileBuild.setCreateTime(new Date());
                        yunfileBuild.setFileType(FilemgrConstants.FILE_TYPE.T01);
                        yunfileBuild.setGroupName(principal.getGroupName());
                        yunfileBuild.setFileUrl(uploadFilePath);
                        yunfileBuild.setFileName(fileName);
                        int fileId = yunfileService.addYunfile(yunfileBuild);

                        // 新增文件日志
                        FileOperalog fileOperalog = new FileOperalog();
                        fileOperalog.setFileName(fileName);
                        fileOperalog.setFileType(FilemgrConstants.FILE_TYPE.T01);
                        fileOperalog.setGroupName(principal.getGroupName());
                        fileOperalog.setCreatePeople(principal.getEmployeeName());
                        fileOperalog.setCreateTime(new Date());
                        fileOperalog.setFileId(fileId);
                        fileOperalog.setFileUrl(uploadFilePath);
                        fileOperalog.setOperatorType(FilemgrConstants.FILE_OPERATOR_TYPE.T01);
                        fileOperalog.setRemark(remark);
                        fileOperalogService.addFileOperalog(fileOperalog);

                        // 查找是否有相同名称（包括类型）的文件，如果有则删除上一个添加的文件
                        YunfileQuery yunfileQuery = new YunfileQuery();
                        yunfileQuery.setParentId(yunfileBuild.getParentId());
                        yunfileQuery.setGroupName(yunfileBuild.getGroupName());
                        yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T01);
                        yunfileQuery.setFileName(yunfileBuild.getFileName());
                        List<Yunfile> needRemoveYunfiles = yunfileService.queryAllYunfiles(yunfileQuery);
                        if(CollectionUtils.isNotEmpty(needRemoveYunfiles)){
                            // 迭代需要删除的同名文件，假设有多个
                            for(Yunfile needDelYunfile : needRemoveYunfiles){
                                // 删除
                                if(needDelYunfile.getFileId() != fileId){
                                    delFile(needDelYunfile.getFileId());
                                }
                            }
                        }
                    }
                }
                return baseResponse;
            }
            baseResponse.setCode(ResponseCode.PARAM_FAIL);
            baseResponse.setData(-1);
            return baseResponse;
        }catch(Exception e){
            if(newFile != null){
                logger.error("文件上传异常,请检查: filePath: {}", newFile);
                newFile.delete();
            }
            baseResponse.setCode(ResponseCode.PARAM_FAIL);
            baseResponse.setData(-2);
            baseResponse.setMsg("系统异常，请联系管理员");
            return baseResponse;
        }
    }

    /**
     * 文件分享页面
     * @param modelMap
     * @param session
     * @return
     */
    @RequestMapping("/shareFileShow")
    @Invoke(logType = LogType.FILE_LOG)
    public String shareFileShow(ModelMap modelMap, HttpSession session){
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        List<YunfileTree> yunfileTrees = new ArrayList<YunfileTree>();
        if(principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            // 默认supper file
            YunfileTree yunfileTree = new YunfileTree();
            yunfileTree.setFolder(true);
            yunfileTree.setLazy(false);
            yunfileTree.setParentId(-1);
            yunfileTree.setKey(0);
            yunfileTree.setTitle(principal.getGroupName());
            yunfileTrees.add(yunfileTree);

            YunfileQuery yunfileQuery = new YunfileQuery();
            yunfileQuery.setGroupName(principal.getGroupName());
            yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T02);
            List<Yunfile> yunfiles = yunfileService.queryAllYunfiles(yunfileQuery);
            // 判断是否二次添加
            Set<Integer> infiniteLoop = new HashSet<Integer>();
            yunfileTree.setChildren(assemblyYunfileTree(yunfiles, 0, infiniteLoop));
        }
        modelMap.put("fileDownloadPrefix", fileDownloadPrefix);
        modelMap.put("jsessionId", session.getId());
        modelMap.put(DEFAULT_ACTIVE_KEY_LINK, session.getAttribute(DEFAULT_ACTIVE_KEY_LINK));
        modelMap.put("yunfileTree", JSON.toJSON(yunfileTrees));
        return "admin/modules/file/share_file_list";
    }

    /**
     * 搜素文件树通过文件名
     * @param fileName
     * @return
     */
    @RequestMapping("/getTreeNodeByName")
    @ResponseBody
    public Object getTreeNodeByName(String fileName){
        BaseResponse baseResponse = new BaseResponse();
        if(StringUtils.isBlank(fileName)){
            baseResponse.setCode(ResponseCode.PARAM_FAIL);
            return baseResponse;
        }
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        List<YunfileTree> yunfileTrees = new ArrayList<YunfileTree>();
        if(principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            // 默认supper file
            YunfileTree yunfileTree = new YunfileTree();
            yunfileTree.setFolder(true);
            yunfileTree.setLazy(false);
            yunfileTree.setParentId(-1);
            yunfileTree.setKey(0);
            yunfileTree.setTitle(principal.getGroupName());
            yunfileTrees.add(yunfileTree);

            // fileName模糊查询
            YunfileQuery yunfileQuery = new YunfileQuery();
            yunfileQuery.setGroupName(principal.getGroupName());
            yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T02);
            yunfileQuery.setFileName(fileName);
            List<Yunfile> yunfiles = yunfileService.queryAllYunfiles(yunfileQuery);

            // 查找所有父结果集
            Set<Integer> parentIds = new HashSet<Integer>();
            if(CollectionUtils.isNotEmpty(yunfiles)){
                // 添加
                for(Yunfile yunfile : yunfiles){
                    String[] parentIdArray = yunfile.getParentIds().split(",");
                    for(String parentId : parentIdArray){
                        parentIds.add(Integer.valueOf(parentId));
                    }
                }
                // 排除
                for(Yunfile yunfile : yunfiles){
                    parentIds.remove(yunfile.getFileId());
                }
                if(!parentIds.isEmpty()){
                    yunfileQuery = new YunfileQuery();
                    yunfileQuery.setGroupName(principal.getGroupName());
                    yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T02);
                    List<Yunfile> yunfileIns = yunfileService.queryAllYunfilesIn(yunfileQuery, new ArrayList<Integer>(parentIds));
                    yunfiles.addAll(yunfileIns);
                }
            }
            // 判断是否二次添加
            Set<Integer> infiniteLoop = new HashSet<Integer>();
            yunfileTree.setChildren(assemblyYunfileTree(yunfiles, 0, infiniteLoop));
        }
        baseResponse.setData(yunfileTrees);
        baseResponse.setCode(ResponseCode.SUCCESS);
        return baseResponse;
    }

    /**
     * 组装文件夹树
     * @param allYunfile
     * @param parentId
     * @param infiniteLoop
     * @return
     */
    private List<YunfileTree> assemblyYunfileTree(List<Yunfile> allYunfile, Integer parentId, Set<Integer> infiniteLoop){
        List<YunfileTree> yunfileTrees = new ArrayList<YunfileTree>();
        // 迭代所有文件
        for(Yunfile yunfile : allYunfile){
            // 当前父文件ID等于parentId并且是文件夹时才组装
            if(yunfile.getParentId().compareTo(parentId) == 0 && FilemgrConstants.FILE_TYPE.T02.equals(yunfile.getFileType())){
                YunfileTree yunfileTree = new YunfileTree();
                try {
                    // 复制
                    yunfileTree.setFolder(true);
                    yunfileTree.setLazy(false);
                    yunfileTree.setParentId(yunfile.getParentId());
                    yunfileTree.setKey(yunfile.getFileId());
                    yunfileTree.setTitle(yunfile.getFileName());
                    yunfileTree.setRemark(yunfile.getRemark());
                } catch (Exception e) {
                    logger.error("文件树组装异常");
                    return null;
                }
                // 判断是否出现死循环
                if(infiniteLoop.contains(yunfile.getFileId())){
                    logger.error("文件树组装异常");
                    return null;
                }
                // 添加,并递归调用
                yunfileTrees.add(yunfileTree);
                infiniteLoop.add(yunfile.getFileId());
                yunfileTree.setChildren(assemblyYunfileTree(allYunfile, yunfile.getFileId(), infiniteLoop));
            }
        }
        return yunfileTrees;
    }

    /**
     * 获取某个文件夹下的文件
     * @param folderId
     * @return
     */
    @RequestMapping("/getFileByFolderId")
    @ResponseBody
    public Object getFileByFolderId(Integer folderId){
        BaseResponse baseResponse = new BaseResponse();
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        List<Yunfile> yunfiles = new ArrayList<Yunfile>();
        // 查找所有当前文件夹下的文件
        if(folderId != null && principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            YunfileQuery yunfileQuery = new YunfileQuery();
            yunfileQuery.setGroupName(principal.getGroupName()); // 组名
            yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T01); // 文件
            yunfileQuery.setParentId(folderId);
            yunfileQuery.setPageSize(1000);// TODO
            yunfiles.addAll(yunfileService.queryAllYunfiles(yunfileQuery));
        }
        baseResponse.setData(yunfiles);
        baseResponse.setCode(ResponseCode.SUCCESS);
        return baseResponse;
    }

    /**
     * 添加文件夹
     * @param folderId
     * @param folderName
     * @param folderRemark
     * @return
     */
    @RequestMapping("/addFolder")
    @ResponseBody
    public Object addFolder(@RequestParam(value = "folderId") Integer folderId,
                            @RequestParam(value = "folderName") String folderName,
                            @RequestParam(value = "folderRemark", required = false) String folderRemark){
        BaseResponse baseResponse = new BaseResponse();
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        if(folderName.length() > 150){
            folderName = folderName.substring(0, 73) + "..." + folderName.substring(folderName.length() - 74, folderName.length());
        }
        if(folderRemark.length() > 150){
            folderRemark = folderRemark.substring(0, 73) + "..." + folderRemark.substring(folderRemark.length() - 74, folderRemark.length());
        }
        // 检查父ID是否存在
        int revId = 0;
        Yunfile yunfileBuild = new Yunfile();
        if(principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            if(folderId == 0){
                // 可直接在虚拟ID下创建文件夹
                yunfileBuild.setParentId(0);
                yunfileBuild.setParentIds("0");
                yunfileBuild.setFileType(FilemgrConstants.FILE_TYPE.T02);
                yunfileBuild.setGroupName(principal.getGroupName());
                yunfileBuild.setCreatePeople(principal.getEmployeeName());
                yunfileBuild.setCreateTime(new Date());
                yunfileBuild.setFileName(folderName);
                yunfileBuild.setRemark(folderRemark);
                revId = yunfileService.addYunfile(yunfileBuild);
            }else{
                YunfileQuery yunfileQuery = new YunfileQuery();
                yunfileQuery.setGroupName(principal.getGroupName());
                yunfileQuery.setFileId(folderId);
                yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T02);
                List<Yunfile> yunfiles = yunfileService.queryAllYunfiles(yunfileQuery);
                Yunfile yunfile = CollectionUtils.getFirst(yunfiles);
                if(yunfile != null){
                    yunfileBuild.setParentId(yunfile.getFileId());
                    yunfileBuild.setParentIds(yunfile.getParentIds() + "," + yunfile.getFileId());
                    yunfileBuild.setFileType(FilemgrConstants.FILE_TYPE.T02);
                    yunfileBuild.setGroupName(principal.getGroupName());
                    yunfileBuild.setCreatePeople(principal.getEmployeeName());
                    yunfileBuild.setCreateTime(new Date());
                    yunfileBuild.setFileName(folderName);
                    yunfileBuild.setRemark(folderRemark);
                    revId = yunfileService.addYunfile(yunfileBuild);
                }
            }
        }
        if(revId > 0){
            // 添加文件夹日志
            FileOperalog fileOperalog = new FileOperalog();
            fileOperalog.setFileName(yunfileBuild.getFileName());
            fileOperalog.setFileType(FilemgrConstants.FILE_TYPE.T02);
            fileOperalog.setGroupName(principal.getGroupName());
            fileOperalog.setCreatePeople(principal.getEmployeeName());
            fileOperalog.setCreateTime(new Date());
            fileOperalog.setFileId(revId);
            fileOperalog.setFileUrl(yunfileBuild.getFileUrl());
            fileOperalog.setOperatorType(FilemgrConstants.FILE_OPERATOR_TYPE.T01);
            fileOperalog.setRemark(yunfileBuild.getRemark());
            fileOperalogService.addFileOperalog(fileOperalog);

            baseResponse.setCode(ResponseCode.SUCCESS);
        }else{
            baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
            baseResponse.setMsg("添加文件夹失败，请重试");
        }
        return baseResponse;
    }

    /**
     * 激活文件树
     * @param session
     * @return
     */
    @RequestMapping(value = "/getTreeNodeByActiveKeys")
    @ResponseBody
    public BaseResponse getTreeNodeByActiveKeys(HttpSession session){
        BaseResponse baseResponse = new BaseResponse();
        List<YunfileTree> yunfileTrees = new ArrayList<YunfileTree>();
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        if(principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            // 默认supper file
            YunfileTree yunfileTree = new YunfileTree();
            yunfileTree.setFolder(true);
            yunfileTree.setLazy(false);
            yunfileTree.setParentId(-1);
            yunfileTree.setKey(0);
            yunfileTree.setTitle(principal.getGroupName());
            yunfileTrees.add(yunfileTree);

            YunfileQuery yunfileQuery = new YunfileQuery();
            yunfileQuery.setGroupName(principal.getGroupName());
            yunfileQuery.setFileType(FilemgrConstants.FILE_TYPE.T02);
            List<Yunfile> yunfiles = yunfileService.queryAllYunfiles(yunfileQuery);
            // 判断是否二次添加
            Set<Integer> infiniteLoop = new HashSet<Integer>();
            yunfileTree.setChildren(assemblyYunfileTree(yunfiles, 0, infiniteLoop));
        }
        baseResponse.setData(yunfileTrees);
        return baseResponse;
    }

    /**
     * 存储文件树节点
     * @param activeKeyLink
     * @param session
     * @return
     */
    @RequestMapping(value = "/saveActiveKeyLink")
    @ResponseBody
    public Object saveActiveKeyLink(String activeKeyLink, HttpSession session) {
        BaseResponse baseResponse = new BaseResponse();
        session.setAttribute(DEFAULT_ACTIVE_KEY_LINK, activeKeyLink);
        return baseResponse;
    }

    /**
     * 删除文件夹
     * @param folderId
     * @return
     */
    @RequestMapping("/removeFolder")
    @ResponseBody
    public Object removeFolder(Integer folderId){
        BaseResponse baseResponse = new BaseResponse();
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        int count = 0;
        if(folderId != null && principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            // 判断是否是根文件夹
            if(folderId == 0){
                baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
                baseResponse.setMsg("根文件夹不可删除，请重试");
                return baseResponse;
            }
            // 判断是否是文件夹
            Yunfile yunfile = yunfileService.queryYunfileById(folderId);
            if(yunfile == null || FilemgrConstants.FILE_TYPE.T01.equals(yunfile.getFileType())){
                baseResponse.setCode(ResponseCode.NOT_EXIST_FAIL);
                baseResponse.setMsg("该文件夹不存在，请重试");
                return baseResponse;
            }
            YunfileQuery yunfileQuery = new YunfileQuery();
            yunfileQuery.setParentId(folderId);
            yunfileQuery.setGroupName(principal.getGroupName());
            Page<Yunfile> yunfiles = yunfileService.queryYunfiles(yunfileQuery);
            if(CollectionUtils.isNotEmpty(yunfiles.getList())){
                //如果存在子文件夹或子文件，则不可删除
                baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
                baseResponse.setMsg("该文件夹下存在其他文件，请先删除其他文件后重试");
                return baseResponse;
            }
            // 删除文件夹
            count = yunfileService.delYunfileById(folderId);
            if(count > 0){
                // 删除文件夹日志
                FileOperalog fileOperalog = new FileOperalog();
                fileOperalog.setFileName(yunfile.getFileName());
                fileOperalog.setFileType(FilemgrConstants.FILE_TYPE.T02);
                fileOperalog.setGroupName(principal.getGroupName());
                fileOperalog.setCreatePeople(principal.getEmployeeName());
                fileOperalog.setCreateTime(new Date());
                fileOperalog.setFileId(folderId);
                fileOperalog.setFileUrl(yunfile.getFileUrl());
                fileOperalog.setOperatorType(FilemgrConstants.FILE_OPERATOR_TYPE.T03);
                fileOperalog.setRemark(yunfile.getRemark());
                fileOperalogService.addFileOperalog(fileOperalog);

                baseResponse.setCode(ResponseCode.SUCCESS);
                return  baseResponse;
            }
        }
        baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
        baseResponse.setMsg("删除失败，请稍后再试");
        return baseResponse;
    }

    /**
     * 修改文件夹
     * @param folderId
     * @param folderName
     * @param folderRemark
     * @return
     */
    @RequestMapping("/updateFolder")
    @ResponseBody
    public Object updateFolder(@RequestParam(value = "folderId") Integer folderId,
                            @RequestParam(value = "folderName") String folderName,
                            @RequestParam(value = "folderRemark", required = false) String folderRemark){
        BaseResponse baseResponse = new BaseResponse();
        if(StringUtils.isBlank(folderName) && StringUtils.isBlank(folderRemark)){
            baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
            baseResponse.setMsg("无需修改，请重试");
            return baseResponse;
        }
        if(folderName.length() > 150){
            folderName = folderName.substring(0, 73) + "..." + folderName.substring(folderName.length() - 74, folderName.length());
        }
        if(folderRemark.length() > 150){
            folderRemark = folderRemark.substring(0, 73) + "..." + folderRemark.substring(folderRemark.length() - 74, folderRemark.length());
        }
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        int count = 0;
        if(principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            // 判断是否是根文件夹
            if(folderId == 0){
                baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
                baseResponse.setMsg("根文件夹不可修改，请重试");
                return baseResponse;
            }else{
                Yunfile yunfile = new Yunfile();
                if(StringUtils.isNotBlank(folderName)){
                    yunfile.setFileName(folderName);
                }
                if(StringUtils.isNotBlank(folderRemark)){
                    yunfile.setRemark(folderRemark);
                }
                yunfile.setUpdatePeople(principal.getEmployeeName());
                yunfile.setUpdateTime(new Date());
                // 通过相应条件修改文件夹
                YunfileExample yunfileExample = new YunfileExample();
                YunfileExample.Criteria criteria = yunfileExample.createCriteria();
                criteria.andGroupNameEqualTo(principal.getGroupName());
                criteria.andFileIdEqualTo(folderId);
                criteria.andFileTypeEqualTo(FilemgrConstants.FILE_TYPE.T02);
                count = yunfileService.updateYunfileByExampleSelective(yunfile, yunfileExample);

                if(count > 0){
                    // 修改文件夹日志
                    FileOperalog fileOperalog = new FileOperalog();
                    fileOperalog.setFileName(yunfile.getFileName());
                    fileOperalog.setFileType(FilemgrConstants.FILE_TYPE.T02);
                    fileOperalog.setGroupName(principal.getGroupName());
                    fileOperalog.setCreatePeople(principal.getEmployeeName());
                    fileOperalog.setCreateTime(new Date());
                    fileOperalog.setFileId(folderId);
                    fileOperalog.setFileUrl(yunfile.getFileUrl());
                    fileOperalog.setOperatorType(FilemgrConstants.FILE_OPERATOR_TYPE.T02);
                    fileOperalog.setRemark(yunfile.getRemark());
                    fileOperalogService.addFileOperalog(fileOperalog);
                }
            }
        }
        if(count > 0){
            baseResponse.setCode(ResponseCode.SUCCESS);
        }else{
            baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
            baseResponse.setMsg("文件夹修改失败，请重试");
        }
        return baseResponse;
    }

    /**
     * 删除文件
     * @param fileId
     * @return
     */
    @RequestMapping("/del")
    @ResponseBody
    public Object delFile(Integer fileId){
        BaseResponse baseResponse = new BaseResponse();
        SystemAuthorizingRealm.Principal principal = SecurityUtils.getPrincipal();
        int count = 0;
        if(fileId != null && principal != null && StringUtils.isNotBlank(principal.getGroupName())){
            Yunfile yunfile = yunfileService.queryYunfileById(fileId);
            if(yunfile != null && yunfile.getGroupName().equals(principal.getGroupName()) && FilemgrConstants.FILE_TYPE.T01.equals(yunfile.getFileType())){
                // step1 物理删除文件
                File removefile = new File(uploadFolderRelease + yunfile.getFileUrl());
                boolean check = true;
                try{
                    for(String removeUrl : yunfile.getFileUrl().split(swfSplit)){
                        fdfsService.deleteFromFastDFS(removeUrl.substring(0, yunfile.getFileUrl().indexOf("/")), removeUrl.substring(yunfile.getFileUrl().indexOf("/") + 1));
                    }
                }catch(Exception e){
                    logger.error("fdfs删除文件异常: fileUrl: {}, fileName: {}", yunfile.getFileUrl(), yunfile.getFileName() );
                    check = false;
                }
                if(check){
                    // step2 物理删除文件记录
                    count = yunfileService.delYunfileById(yunfile.getFileId());
                    if(count > 0){
                        // 删除文件日志
                        FileOperalog fileOperalog = new FileOperalog();
                        fileOperalog.setFileName(yunfile.getFileName());
                        fileOperalog.setFileType(FilemgrConstants.FILE_TYPE.T01);
                        fileOperalog.setGroupName(principal.getGroupName());
                        fileOperalog.setCreatePeople(principal.getEmployeeName());
                        fileOperalog.setCreateTime(new Date());
                        fileOperalog.setFileId(fileId);
                        fileOperalog.setFileUrl(yunfile.getFileUrl());
                        fileOperalog.setOperatorType(FilemgrConstants.FILE_OPERATOR_TYPE.T03);
                        fileOperalog.setRemark(yunfile.getRemark());
                        fileOperalogService.addFileOperalog(fileOperalog);
                    }
                }
            }
        }
        if(count > 0){
            baseResponse.setCode(ResponseCode.SUCCESS);
        }else{
            baseResponse.setCode(ResponseCode.BUSINESS_FAIL);
            baseResponse.setMsg("文件删除失败，请重试");
        }
        return baseResponse;
    }

    /**
     * 文件日志列表
     * @param fileOperalogQuery
     * @param request
     * @param modelMap
     * @return
     */
    @RequestMapping("/fileOperalogShow")
    public String fileOperalogShow(FileOperalogQuery fileOperalogQuery, HttpServletRequest request, ModelMap modelMap){
        fileOperalogQuery.setRequestUrl(UrlUtils.getLookupPathForRequest(request));
        Page<FileOperalog> fileOperalogPage = fileOperalogService.queryYunfiles(fileOperalogQuery);
        modelMap.put("fileOperalogPage", fileOperalogPage);
        return "admin/modules/file/file_oplog_list";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        File folder = new File(uploadFolderRelease);
        if(!folder.exists()){
            folder.mkdirs();
        }
        folder = new File(uploadFolderTemp);
        if(!folder.exists()){
            folder.mkdirs();
        }
    }
}
